<?php


namespace App\Services\Goods;

use App\Common\ResponseCode;
use App\Exceptions\BusinessException;
use App\Models\Goods\Category;
use App\Params\Backend\CategoryListParams;
use App\Params\Backend\CategoryUpdateParam;
use App\Services\BaseService;

/**
 * 商品分类相关业务类
 *
 * @author WangBin
 * @date 2021-09-24
 * @package App\Http\Services
 */
class CategoryService extends BaseService
{
    /**
     * 保存分类信息
     *
     * @param CategoryUpdateParam $data
     * @return mixed
     * @throws BusinessException
     */
    public function update(CategoryUpdateParam $data)
    {
        if(!empty($data->getCategoryId())) {
            $category = Category::getById($data->getCategoryId());
            if(is_null($category)) {
                throw new BusinessException(ResponseCode::CATEGORY_NOT_FOUND);
            }
        } else {
            $data->path = 0;
        }
        $categoryId = Category::saveData($data);
        // 获取path
        $parentIds = [];
        $this->getParentIds($parentIds, $categoryId);
        Category::updateData($categoryId, ['path' => implode('/', $parentIds)]);
        return $categoryId;
    }

    /**
     * 分类列表
     *
     * @param CategoryListParams $filter
     * @return array
     */
    public function getList(CategoryListParams $filter)
    {
        return $this->toList(Category::getByFilter($filter), $filter->getPage(), $filter->getPageSize());
    }

    /**
     * 获取分类的path
     *
     * @param array $parentIds
     * @param int $categoryId
     * @return array
     */
    public function getParentIds(array &$parentIds, int $categoryId)
    {
        $category = Category::query()->where('category_id', $categoryId)->first();
        $parent = Category::query()->where('category_id', $category->parent_id)->first();
        $parentIds[] = $categoryId;
        if(is_null($parent)) {
            sort($parentIds, SORT_ASC);
            return $parentIds;
        }
        $this->getParentIds($parentIds, $category->parent_id);
    }

    /**
     * 根据层级获取分类
     *
     * @param int $level
     * @return Category[]
     */
    public function getChild(int $level)
    {
        return Category::getChild($level);
    }

    /**
     * 获取分类选择器（含父子关系）
     *
     * @return array
     */
    public function getTree()
    {
        $categories = Category::query()->where('is_active', 1)
            ->select(['category_id as value', 'name as label', 'parent_id', 'level'])
            ->orderBy('sort_num', 'asc')
            ->get();
        $tree = $this->makeTree($categories);
        return $tree;
    }

    /**
     * 获取H5商品分类（含父子关系）
     *
     * @return array
     */
    public function getH5Tree()
    {
        $categories = Category::query()->where('is_active', 1)
            ->select(['category_id as id', 'name', 'parent_id as pid', 'level', 'icon_url as image'])
            ->orderBy('sort_num', 'asc')
            ->get();
        $tree = $this->makeH5Tree($categories)[0];
        // 设置type为4，H5需要
        $tree['type'] = 4;
        return $tree;
    }

    /**
     * 获取中台分类选择器
     *
     * @return mixed
     */
    public function getSelectTree()
    {
        $categories = Category::query()->where('is_active', 1)
            ->select(['category_id as id', 'name as title', 'parent_id as pid', 'level'])
            ->orderBy('sort_num', 'asc')
            ->get();
        $tree = $this->makeH5Tree($categories);
        return $tree;
    }

    /**
     * 获取中台商品分类选择器
     *
     * @return mixed
     */
    public function getBackendSelectTree()
    {
        $categories = Category::query()->where('is_active', 1)
            ->select(['category_id as value', 'name as label', 'parent_id as pid', 'level'])
            ->orderBy('sort_num', 'asc')
            ->get();
        $tree = $this->makeBackendTree($categories);
        return $tree;
    }

    /**
     * 递归获取结构树
     *
     * @param  array $data  数据源
     * @param  integer $parentId 父类id
     * @return array 组装好的树
     */
    private function makeTree(&$data, $parentId = 0)
    {
        $tree = [];
        foreach($data as $k => $v)
        {
            if($v['parent_id'] == $parentId)
            { //父亲找到儿子
                $v['children'] = self::makeTree($data, $v['value']);
                $tree[] = $v;
                unset($data[$k]); // 释放原始数据变量
                if(empty($v['children'])) {
                    unset($v['children']);
                }
            }
        }
        return $tree;
    }

    /**
     * 递归获取结构树（H5）
     *
     * @param  array $data  数据源
     * @param  integer $parentId 父类id
     * @return array 组装好的树
     */
    private function makeH5Tree(&$data, $parentId = 0)
    {
        $tree = [];
        foreach($data as $k => $v)
        {
            if($v['pid'] == $parentId)
            { //父亲找到儿子
                $v['children'] = self::makeH5Tree($data, $v['id']);
                $tree[] = $v;
                unset($data[$k]); // 释放原始数据变量
                if(empty($v['children'])) {
                    unset($v['children']);
                }
            }
        }
        return $tree;
    }

    /**
     * 递归获取结构树（中台）
     *
     * @param  array $data  数据源
     * @param  integer $parentId 父类id
     * @return array 组装好的树
     */
    private function makeBackendTree(&$data, $parentId = 0)
    {
        $tree = [];
        foreach($data as $k => $v)
        {
            if($v['pid'] == $parentId)
            { //父亲找到儿子
                $v['children'] = self::makeBackendTree($data, $v['value']);
                $tree[] = $v;
                unset($data[$k]); // 释放原始数据变量
                if(empty($v['children'])) {
                    unset($v['children']);
                }
            }
        }
        return $tree;
    }

    /**
     * 获取分类详情
     *
     * @param $categoryId
     * @return
     * @throws
     */
    public function get($categoryId)
    {
        $category = Category::getById($categoryId);
        if(is_null($category)) {
            throw new BusinessException(ResponseCode::CATEGORY_NOT_FOUND);
        }
        $category->parent_name = Category::getById($category->parent_id)->name;
        return $category;
    }

    /**
     * 根据层级获取分类
     *
     * @param int $level
     * @return
     */
    public function getListByLevel(int $level)
    {
        return Category::query()->where('level', $level)->where('is_active', 1)->get();
    }

    /**
     * 删除分类
     *
     * @param int $categoryId
     * @return bool|mixed|null
     * @throws BusinessException
     */
    public function delete(int $categoryId)
    {
        $category = Category::getById($categoryId);
        if(is_null($category)) {
            throw new BusinessException(ResponseCode::CATEGORY_NOT_FOUND);
        }
        // 是否有子分类
        $count = Category::getChildCount($categoryId);
        if($count > 0) {
            throw new BusinessException(ResponseCode::CATEGORY_HAS_CHILD);
        }
        return $category->delete();
    }

    /**
     * 停用/启用分类
     *
     * @param int $categoryId
     * @return int
     * @throws BusinessException
     */
    public function enable(int $categoryId)
    {
        $category = Category::getById($categoryId);
        if(is_null($category)) {
            throw new BusinessException(ResponseCode::CATEGORY_NOT_FOUND);
        }
        $isActive = $category->is_active == 1 ? 0 : 1;
        return Category::enable($categoryId, $isActive);
    }

    /**
     * 获取分类子分类
     *
     * @param int $categoryId
     * @return \Illuminate\Database\Eloquent\Builder[]|\Illuminate\Database\Eloquent\Collection
     */
    public function getChilds(int $categoryId)
    {
        return Category::getByFilter(['parent_id' => $categoryId])->get();
    }
}
